/**
 * SSE (Server-Sent Events) 流式请求工具类
 * 基于 Microsoft 开源的 @microsoft/fetch-event-source 实现
 * 提供更好的错误处理和重连机制
 */

import { fetchEventSource } from '@microsoft/fetch-event-source';
import { getCookieFun } from './storage';

// 流式消息类型定义
export interface StreamMessage {
  id?: string;
  event?: string;
  data: string;
  retry?: number;
}

// 流式请求配置选项
export interface StreamOptions {
  method?: 'GET' | 'POST';
  headers?: Record<string, string>;
  body?: string | FormData | URLSearchParams;
  signal?: AbortSignal;
  onOpen?: (response: Response) => void;
  onMessage?: (message: StreamMessage) => void;
  onClose?: () => void;
  onError?: (error: Error) => void;
}

// 连接状态枚举
export enum StreamState {
  IDLE = 'idle',
  CONNECTING = 'connecting',
  CONNECTED = 'connected',
  CLOSED = 'closed',
  ERROR = 'error',
}

/**
 * Microsoft fetch-event-source 流式客户端封装类
 */
export class StreamClient {
  private url: string;
  private options: StreamOptions;
  private abortController: AbortController | null = null;
  private state: StreamState = StreamState.IDLE;

  constructor(url: string, options: StreamOptions = {}) {
    this.url = url;
    this.options = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json; charset=utf-8',
        Accept: 'text/event-stream, application/json, */*',
        'Accept-Charset': 'utf-8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Cache-Control': 'no-cache',
        Connection: 'keep-alive',
        ...options.headers,
      },
      ...options,
    };
    if (url.indexOf('user') > -1) {
      this.options.headers!.Authorization = getCookieFun('token') || '';
    }
  }

  /**
   * 开始流式连接
   */
  async connect(): Promise<void> {
    try {
      this.state = StreamState.CONNECTING;
      this.abortController = new AbortController();

      await fetchEventSource(this.url, {
        method: this.options.method,
        headers: this.options.headers,
        body: this.options.body,
        signal: this.abortController.signal,

        onopen: async response => {
          console.log('SSE 响应状态:', response.status);
          console.log('SSE 响应头:', Object.fromEntries(response.headers.entries()));

          if (response.ok && response.headers.get('content-type')?.includes('text/event-stream')) {
            console.log('流式连接已建立');
            this.state = StreamState.CONNECTED;
            this.options.onOpen?.(response);
          } else {
            // 详细的错误信息
            const errorDetails = {
              status: response.status,
              statusText: response.statusText,
              contentType: response.headers.get('content-type'),
              headers: Object.fromEntries(response.headers.entries()),
            };
            console.error('SSE 连接失败详情:', errorDetails);
            this.options.onError?.(new Error('SSE 连接失败详情:' + JSON.stringify(errorDetails)));

            if (response.status === 406) {
              throw new Error(
                `406 Not Acceptable: 服务器无法提供客户端请求的内容类型。请检查 Accept 头部设置。响应内容类型: ${response.headers.get(
                  'content-type'
                )}`
              );
            } else {
              throw new Error(`连接失败: ${response.status} ${response.statusText}`);
            }
          }
        },

        onmessage: event => {
          try {
            const message: StreamMessage = {
              id: event.id,
              event: event.event,
              data: event.data,
            };
            this.options.onMessage?.(message);
          } catch (error) {
            console.error('解析流式消息失败:', error);
            this.options.onError?.(error as Error);
          }
        },

        onclose: () => {
          console.log('流式连接已关闭');
          this.state = StreamState.CLOSED;
          this.options.onClose?.();
        },

        onerror: error => {
          console.error('流式连接错误:', error);
          this.state = StreamState.ERROR;
          this.options.onError?.(error as Error);
          throw error; // 让 fetch-event-source 处理重连
        },
      });
    } catch (error) {
      console.error('启动流式连接失败:', error);
      this.state = StreamState.ERROR;
      this.options.onError?.(error as Error);
      throw error;
    }
  }

  /**
   * 关闭流式连接
   */
  close(): void {
    if (this.abortController) {
      this.abortController.abort();
      this.abortController = null;
    }
    this.state = StreamState.CLOSED;
    console.log('流式连接已手动关闭');
  }

  /**
   * 获取当前连接状态
   */
  getState(): StreamState {
    return this.state;
  }

  /**
   * 是否正在连接中
   */
  isConnecting(): boolean {
    return this.state === StreamState.CONNECTING;
  }

  /**
   * 是否已连接
   */
  isConnected(): boolean {
    return this.state === StreamState.CONNECTED;
  }

  /**
   * 是否已关闭
   */
  isClosed(): boolean {
    return this.state === StreamState.CLOSED;
  }
}

/**
 * 创建流式客户端的工厂函数
 */
export function createStreamClient(url: string, options: StreamOptions = {}): StreamClient {
  return new StreamClient(url, options);
}

/**
 * 流式聊天请求函数
 * @param message 用户消息
 * @param chatId 聊天 ID
 * @param onChunk 接收数据块的回调
 * @param onComplete 完成回调
 * @param onError 错误回调
 */
export async function streamChatRequest(
  params: Record<string, any>,
  onChunk: (chunk: string) => void,
  onComplete?: () => void,
  onError?: (error: Error) => void
): Promise<StreamClient> {
  const streamClient = createStreamClient('/api/user_multi_round_dialogue/', {
    method: 'POST',
    body: JSON.stringify({
      ...params,
      timestamp: Date.now(),
    }),
    onMessage: streamMessage => {
      try {
        console.log('🚀 ~ streamMessage:', streamMessage);
        const data = JSON.parse(streamMessage.data);

        // 处理不同类型的流式消息
        if (data.content) {
          onChunk(data.content || '');
        } else if (data.done) {
          onComplete?.();
          streamClient.close();
        } else if (data.type === 'error') {
          onError?.(new Error(data.message || '流式请求出错'));
          streamClient.close();
        }
      } catch (error) {
        console.error('解析流式消息失败:', error);
        onError?.(error as Error);
      }
    },
    onError: error => {
      console.error('流式连接错误:', error);
      onError?.(error);
    },
    onClose: () => {
      console.log('流式连接关闭');
    },
  });

  try {
    await streamClient.connect();
    return streamClient;
  } catch (error) {
    console.error('启动流式聊天失败:', error);
    onError?.(error as Error);
    throw error;
  }
}

/**
 * 降级方案：普通HTTP请求模拟流式效果
 */
async function fallbackStreamRequest(
  params: Record<string, any>,
  onChunk: (chunk: string) => void,
  onComplete?: () => void,
  onError?: (error: Error) => void
): Promise<void> {
  try {
    console.log('使用降级方案：普通HTTP请求模拟流式效果');

    // 这里应该调用你现有的聊天API
    const response = await fetch('/api/user_multi_round_dialogue/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: getCookieFun('token') || '',
      },
      body: JSON.stringify({
        ...params,
        timestamp: Date.now(),
      }),
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const result = await response.json();
    const content = result.data?.content || result.message || '抱歉，我无法回复这个问题。';

    // 模拟流式输出效果
    const chunks = content.match(/.{1,3}/g) || [content];

    for (let i = 0; i < chunks.length; i++) {
      await new Promise(resolve => setTimeout(resolve, 50));
      onChunk(chunks[i]);
    }

    onComplete?.();
  } catch (error) {
    console.error('降级请求失败:', error);
    onError?.(error as Error);
  }
}

/**
 * 简化的流式请求 Hook
 * 返回控制函数和状态
 */
export function useStreamChat() {
  let currentStreamClient: StreamClient | null = null;
  let isAborted = false;

  const startStream = async (
    params: Record<string, any>,
    callbacks: {
      onChunk: (chunk: string) => void;
      onComplete?: () => void;
      onError?: (error: Error) => void;
    }
  ) => {
    try {
      // 如果有正在进行的连接，先关闭
      if (currentStreamClient) {
        currentStreamClient.close();
      }

      isAborted = false;

      try {
        // 首先尝试真正的流式请求
        currentStreamClient = await streamChatRequest(
          params,
          callbacks.onChunk,
          () => {
            if (!isAborted) {
              callbacks.onComplete?.();
              currentStreamClient = null;
            }
          },
          error => {
            console.error('流式请求失败，尝试降级方案:', error);

            // 如果是 406 错误，使用降级方案
            if (error.message.includes('406')) {
              // fallbackStreamRequest(
              //   params,
              //   chatId,
              //   callbacks.onChunk,
              //   callbacks.onComplete,
              //   callbacks.onError
              // );
            } else {
              callbacks.onError?.(error);
            }
            currentStreamClient = null;
          }
        );

        return currentStreamClient;
      } catch (sseError) {
        console.warn('SSE 连接失败，使用降级方案:', sseError);

        // SSE 失败时使用降级方案
        // await fallbackStreamRequest(
        //   params,
        //   chatId,
        //   callbacks.onChunk,
        //   callbacks.onComplete,
        //   callbacks.onError
        // );

        return null;
      }
    } catch (error) {
      console.error('启动流式聊天失败:', error);
      callbacks.onError?.(error as Error);
      throw error;
    }
  };

  const stopStream = () => {
    isAborted = true;
    if (currentStreamClient) {
      currentStreamClient.close();
      currentStreamClient = null;
    }
  };

  const isStreaming = () => {
    return currentStreamClient?.isConnected() ?? false;
  };

  return {
    startStream,
    stopStream,
    isStreaming,
  };
}

export default StreamClient;
